package awk;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

import dynamic.DynamicEngine;

/**
 * @author zniu
 *
 */
public class AWKFactory {
    private String varibles ;
    private String begin ;
    private String end ;
    private String body ;
    private String file ;
    private String awkSource ;
    private String importC ; 
    private ArrayList<String> function = new ArrayList<String>();
     public String getClassString(){
         String cbody =//"package awk;" + "\n" +
             this.importC +
             "public  class LineHandlerT extends awk.LineHandler{ "
                 +"\n\t" + varibles + "\n"  
                     +"\n\t  public  LineHandlerT(){\n" +
                 "\n\t}" 

                 +"\n\t public  void begin(){ "+"\n" 
                     + "\n\t\t"+begin + "\n" 
                  +"\n\t}"  
                 + "\n\t public void body(String[] args){"
                     +"\n\t\t" + body 
                 +"\n\t }"
                 /* end  */
                + "\n\t public void end(){"
                    +"\n\t\t" + end 
                 +"\n }"  
                 +getFunctionString() +"\n" +
                 "}";
         return cbody ;
     }
     public String getFunctionString(){
         String f ="" ;
         for( int i=0; i< this.function.size(); ++i ){
             f+=function.get(i)+"\n";
         }
         return f ;
     }
    public void setVaribles(String varibles) {
        this.varibles = varibles;
    }
    public void setBegin(String begin) {
        this.begin = begin;
    }
    public void setEnd(String end) {
        this.end = end;
    }
    public void setBody(String body) {
        this.body = body;
    }
    public String getBegin(String whole) throws Exception{
        int s=whole.indexOf("BEGIN=[");
        if( s < 0 ) return ";" ;
        int end = whole.indexOf("]E-BEGIN") ;
        if( end < 0 ) throw new Exception("did not find E-BEGIN tag") ;
        String begin = whole.substring(s+7, end);
        return begin ;
    }
    public String getBody(String whole) throws Exception{
        int s=whole.indexOf("BODY=[");
        if( s < 0 ) return ";" ;
        
        int end = whole.indexOf("]E-BODY") ;
        if( end < 0 ) throw new Exception("did not find E-BODY tag") ;

        String begin = whole.substring(s+6, end);
        return begin  ;
    }
    public String getEnd(String whole) throws Exception{
        int s=whole.indexOf("END=[");
        if( s < 0 ) return ";" ;
        int end = whole.indexOf("]E-END") ;
        if( end < 0 ) throw new Exception("did not find E-END tag") ;

        String begin = whole.substring(s+5, end );
        return begin  ;
    }
    public String getVariable(String whole) throws Exception{
        int s=whole.indexOf("VAR=[");
        if( s < 0 ) return "" ;
        int end = whole.indexOf("]E-VAR") ;
        if( end < 0 ) throw new Exception("did not find E-VAR tag") ;

        String begin = whole.substring(s+5, end);
        return begin  ;
    }
    public String getImport(String whole) throws Exception{
        int s=whole.indexOf("IMPORT=[");
        if( s < 0 ) return "" ;
        
        int end = whole.indexOf("]E-IMPORT") ;
        if( end < 0 ) throw new Exception("did not find E-IMPORT tag") ;

        String begin = whole.substring(s+8, end);
        return begin  ;
    }

    public void getFunction(String context) throws Exception {
        String sTag = "FUN=[" ;
        String eTag = "]E-FUN" ;
        
        int begin = context.indexOf(sTag );
        
        while (begin >= 0) {
            String record = "";
            int end = context.indexOf(eTag, begin);
            if( end < 0) throw new Exception(" miss ]E-FUN tag") ;
            record = context.substring(begin +sTag.length(),  end);
            record += "\n" ;
            this.function.add(record) ;
             begin = context.indexOf(sTag, end+eTag.length() );
        }
        System.out.println("finish get function") ;
    }
    
    public String setSourceFromFile(String file) throws Exception{
        BufferedReader in = new BufferedReader(new FileReader(file));
        String line="";
        String context ="" ;
        while((line = in.readLine())!=null) context += line +"\n" ;
        this.begin = this.getBegin(context) ;
        this.varibles = this.getVariable(context) ;
        this.body = this.getBody(context) ;
        this.end = this.getEnd(context) ;
        this.importC = this.getImport(context) ;
        getFunction(context) ;
        this.awkSource = getClassString() ;
        return awkSource ;
    }
    public LineHandler getAwk() throws IllegalAccessException, InstantiationException{
        DynamicEngine de = DynamicEngine.getInstance();
        LineHandler instance =  (LineHandler) de.javaCodeToObject("LineHandlerT",awkSource);
        return instance;
    }
    public void initSource(){
        
    }
    
    
    
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, IllegalArgumentException, InvocationTargetException{
//    	Factory fac = new Factory() ;
//    	fac.setSourceFromFile("src/awkcase.awk") ;
    	
        AWKFactory f = new AWKFactory() ;
        f.setVaribles(" String line = \"begin\";") ;
        f.setBegin(" System.out.println(\"begin, line=\" + line ); ") ;
        f.setBody( " System.out.println(\"body, line=\" + line ); ") ;
        f.setEnd( " System.out.println(\"end, line=\" + line ); ") ;
        
        String cbody = f.getClassString() ;
        System.out.println(cbody) ;
        DynamicEngine de = DynamicEngine.getInstance();
        Object instance =  de.javaCodeToObject("LineHandlerT",cbody);
        Method[] ms = instance.getClass().getDeclaredMethods() ;
        for( int i = 0; i< ms.length ; ++i){
            if( ms[i].getName().equals("handleOneLine"))
                ms[i].invoke(instance, "test") ;
        }
//        ((LineHandler)instance).handleOneLine("test 000000000");

    }

 
        
}
